package com.hongyan.util;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class JDBCUtils<T> {
    public static Connection getConnection() {
        return connection;
    }

    private static Connection connection;

    static {
        try {
            // 加载数据库驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/javashixun?serverTimezone=UTC&useSSL=false", "root", "123456");
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
    }

    public static <T> List<T> query(String sql, Class<T> cls) {
        try {
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            List<T> result = new ArrayList<>();
            ResultSet resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                T t = cls.newInstance();
                ResultSetMetaData metaData = resultSet.getMetaData();
                for (int i = 1; i <= metaData.getColumnCount(); i++) {
                    String columnName = metaData.getColumnName(i);
                    Object value = resultSet.getObject(columnName);
                    Field declaredField = cls.getDeclaredField(columnName);
                    declaredField.setAccessible(true);
                    declaredField.set(t, value);
                }
                result.add(t);
            }
            return result;
        } catch (SQLException | NoSuchFieldException | InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> List<T> queryBycondition(String sql, Class<T> cls, Object... args) {
        try {
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            if (args.length > 0) {
                for (int i = 0; i < args.length; i++) {
                    Object arg = args[i];
                    if (arg instanceof String) {
                        preparedStatement.setString(i + 1, (String) arg);
                    } else if (arg instanceof Integer) {
                        preparedStatement.setInt(i + 1, (Integer) arg);
                    } else if (arg instanceof Date) {
                        preparedStatement.setDate(i + 1, (Date) arg);
                    } else if (arg instanceof Float) {
                        preparedStatement.setFloat(i + 1, (Float) arg);
                    } else if (arg instanceof Double) {
                        preparedStatement.setDouble(i + 1, (Double) arg);
                    } else if (arg instanceof Blob) {
                        preparedStatement.setBlob(i + 1, (Blob) arg);
                    } else if (arg instanceof byte[]) {
                        preparedStatement.setBytes(i + 1, (byte[]) arg);
                    }
                }
            }
            List<T> result = new ArrayList<>();
            ResultSet resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                T t = cls.newInstance();
                ResultSetMetaData metaData = resultSet.getMetaData();
                for (int i = 1; i <= metaData.getColumnCount(); i++) {
                    String columnName = metaData.getColumnName(i);
                    Object value = resultSet.getObject(columnName);
                    Field declaredField = cls.getDeclaredField(columnName);
                    declaredField.setAccessible(true);
                    declaredField.set(t, value);
                }
                result.add(t);
            }
            return result;
        } catch (SQLException | NoSuchFieldException | InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T queryByconditionOne(String sql, Class<T> cls, Object... args) {
        List<T> result = queryBycondition(sql, cls, args);
        if (!result.isEmpty()) {
            return result.get(0);
        }
        return null;
    }


    public static int update(String sql, Object... args) {
        try {
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            if (args.length > 0) {
                for (int i = 0; i < args.length; i++) {
                    Object arg = args[i];
                    if (arg instanceof String) {
                        preparedStatement.setString(i + 1, (String) arg);
                    } else if (arg instanceof Integer) {
                        preparedStatement.setInt(i + 1, (Integer) arg);
                    } else if (arg instanceof Date) {
                        preparedStatement.setDate(i + 1, (Date) arg);
                    } else if (arg instanceof Float) {
                        preparedStatement.setFloat(i + 1, (Float) arg);
                    } else if (arg instanceof Double) {
                        preparedStatement.setDouble(i + 1, (Double) arg);
                    } else if (arg instanceof Blob) {
                        preparedStatement.setBlob(i + 1, (Blob) arg);
                    } else if (arg instanceof byte[]) {
                        preparedStatement.setBytes(i + 1, (byte[]) arg);
                    } else if (arg instanceof BigDecimal) {
                        preparedStatement.setBigDecimal(i + 1, (BigDecimal) arg);
                    } else if (arg instanceof Boolean) {
                        preparedStatement.setBoolean(i + 1, (Boolean) arg);
                    } else if (arg instanceof Timestamp) {
                        preparedStatement.setTimestamp(i + 1, (Timestamp) arg);
                    } else {
                        preparedStatement.setObject(i + 1, arg);
                    }
                }
            }
            return preparedStatement.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }


}
